﻿using LightCAD.Core.Elements.Basic;
using System.IO;

namespace LightCAD.Drawing.Actions.Action
{
    public class RasterImageAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;

        public RasterImageAction() { }
        public RasterImageAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令 ：RasterImage");
        }

        static RasterImageAction()
        {
            CommandName = "RasterImage";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "RasterImage",
                Description = "附加图片",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="指定图片路径：" },
                    new LcCreateStep{ Name="Step3", Options="指定旋转角度：" },
                    new LcCreateStep{ Name="Step1", Options="指定图片坐标：" },
                    new LcCreateStep{ Name="Step2", Options="指定缩放比例：" },
                }
            };
        }

        internal static void Initilize()
        {
            ElementActions.RasterImage = new RasterImageAction();
            LcDocument.ElementActions.Add(BuiltinElementType.RasterImage, ElementActions.RasterImage);
        }

        private PointInputer inputer;

        private string imagePath;
        private Vector2 firstPoint;
        private double scale = 1;
        private double rotate = 0;

        private double width;
        private double height;

        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            var curMethod = CreateMethods[0];
            this.inputer = new PointInputer(this.docEditor);

            if (args == null || args.Length == 0)
            {
                var filePaths = await AppRuntime.UISystem.OpenFileDialog();
                if (filePaths == null) { this.Cancel(); goto End; };
                imagePath = filePaths[0];
                var skBitmap = SKBitmap.Decode(this.imagePath);
                this.width = skBitmap.Width;
                this.height = skBitmap.Height;
                goto Step1;
            }
        Step0:
            var step0 = curMethod.Steps[0];
            var result0 = await inputer.Execute(step0.Options);
            if (inputer.isCancelled || result0 == null) { this.Cancel(); goto End; }
            if (result0.ValueX == null)
            {
                if (!string.IsNullOrEmpty(result0.Option) && File.Exists(result0.Option))
                {
                    this.imagePath = result0.Option;
                    var skBitmap = SKBitmap.Decode(this.imagePath);
                    this.width = skBitmap.Width;
                    this.height = skBitmap.Height;
                    goto Step1;
                }
            }
            goto Step0;
        Step1:
            var step1 = curMethod.Steps[1];
            var result1 = await inputer.Execute(step1.Options);
            if (inputer.isCancelled || result1 == null) { this.Cancel(); goto End; }

            if (result1.ValueX == null)
            {
                if (!string.IsNullOrEmpty(result1.Option) && double.TryParse(result1.Option, out double rotateTemp))
                {
                    rotate = rotateTemp;
                }
                // 格式不对直接使用默认值
                goto Step2;
            }
            goto Step1;
        Step2:
            var step2 = curMethod.Steps[2];
            var result2 = await inputer.Execute(step2.Options);
            if (inputer.isCancelled || result2 == null) { this.Cancel(); goto End; }

            if (result2.ValueX == null)
            {
                goto Step2;
            }
            else
            {
                this.firstPoint = (Vector2)result2.ValueX;
                goto Step3;
            }
        Step3:
            var step3 = curMethod.Steps[3];
            var result3 = await inputer.Execute(step3.Options);
            if (inputer.isCancelled || result3 == null) { this.Cancel(); goto End; }

            if (result3.ValueX == null)
            {
                if (!string.IsNullOrEmpty(result3.Option) && double.TryParse(result3.Option, out double scaleTmpe))
                {
                    scale = scaleTmpe;
                }
            }
            else
            {
                var endPoint = (Vector2)result3.ValueX;
                scale = Vector2.Distance(firstPoint, endPoint);
            }

            CreatRasterImage();
            goto End;
        End:
            this.EndCreating();
        }

        public override void DrawAuxLines(SKCanvas canvas)
        {
            if (firstPoint != null)
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);

                var movePoint = mp.ToSKPoint();
                var point = this.vportRt.ConvertWcsToScr(firstPoint).ToSKPoint();
                canvas.DrawLine(point, movePoint, Constants.auxOrangeDashPen);

                scale = Vector2.Distance(firstPoint, wcs_mp) * this.vportRt.Viewport.Scale;
                var widthTmp = scale;
                var heightTmp = scale * height / width ;

                canvas.DrawRect(point.X, point.Y, (float)widthTmp, -(float)heightTmp, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
            }
        }

        public void CreatRasterImage()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("RasterImage");

            var RasterImage = doc.CreateObject<LcRasterImage>();
            RasterImage.FirstPoint = this.firstPoint;
            RasterImage.Width = this.scale;
            RasterImage.Height = this.scale * this.height / this.width;
            RasterImage.ScaleValue = this.scale;
            RasterImage.RotateAngle = this.rotate;
            RasterImage.ImagePath = this.imagePath;
            RasterImage.EndPoint = new Vector2(this.firstPoint.X + RasterImage.Width, this.firstPoint.Y + RasterImage.Height);
            RasterImage.Box2D = new Box2().SetFromPoints(RasterImage.FirstPoint, RasterImage.EndPoint);

            doc.ModelSpace.InsertElement(RasterImage);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }

        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {
            var RasterImage = element as LcRasterImage;

            var pen = this.GetDrawPen(RasterImage);

            var start = this.vportRt.ConvertWcsToScr(matrix.MultiplyPoint(RasterImage.FirstPoint)).ToSKPoint();

            var width = RasterImage.Width * this.vportRt.Viewport.Scale;
            var height = RasterImage.Height * this.vportRt.Viewport.Scale;

            var skRect = new SKRect(start.X, start.Y - (float)(height), start.X + (float)(width), start.Y);

            var skBitmap = SKBitmap.Decode(RasterImage.ImagePath);

            if (skBitmap != null )
            {
                if (pen == Constants.defaultPen)
                {
                    using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                    {
                        canvas.DrawBitmap(skBitmap, skRect, elePen);
                    }
                }
                else
                {
                    canvas.DrawBitmap(skBitmap, skRect, pen);
                }
            }
            else
            {
                canvas.DrawRect(skRect, pen);
                using (var paint = new SKPaint())
                {
                    var text = Path.GetFileName(RasterImage.ImagePath);
                    //得到文字长度
                    var tRect = new SKRect();
                    //文字长度
                    var tWidth = paint.MeasureText(text, ref tRect);

                    var textScale = 10 * skRect.Width / tWidth;
                    var fontManager = SKFontManager.Default;
                    var emojiTypeface = fontManager.MatchCharacter('时');
                    paint.TextSize = textScale;
                    paint.TextAlign = SKTextAlign.Center;
                    //抗锯齿
                    paint.IsAntialias = false;
                    paint.Color = new SKColor(0x42, 0x81, 0xA4);
                    paint.IsStroke = false;
                    paint.Typeface = emojiTypeface;

                    SKFont sKFont = new SKFont();
                    // 获取宋体在字体集合中的下标
                    var index = SKFontManager.Default.FontFamilies.ToList().IndexOf("宋体");
                    // 创建宋体字形
                    var songtiTypeface = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
                    sKFont.Typeface = songtiTypeface;
                    sKFont.Size =  textScale;

                    canvas.DrawText(text, start.X + (float)width / 2, start.Y - (float)height / 2 + tRect.Height, sKFont, paint);
                }
            }
        }

        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var image = element as LcRasterImage;

            var grips = new List<ControlGrip>();

            var gripRightTop = new ControlGrip
            {
                Element = image,
                Name = "RightTop",
                Position = image.Box2D.RightTop
            };
            grips.Add(gripRightTop);

            return grips.ToArray();
        }

        private string _gripName;
        private Vector2 _position;
        private LcRasterImage _RasterImage;

        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            var RasterImage = element as LcRasterImage;

            _RasterImage = RasterImage;
            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                if (gripName == "RightTop")
                {
                    //得到移动的距离
                    double newscale = Vector2.Distance(_RasterImage.FirstPoint, _position);
                    var newwidth = newscale;
                    var newheight = newscale * _RasterImage.Height / _RasterImage.Width;
                    var newend = new Vector2(_RasterImage.FirstPoint.X + newwidth, _RasterImage.FirstPoint.Y + newheight);

                    _RasterImage.Set(end: newend, width: newwidth, height: newheight, scale: newscale);
                }
            }
        }

        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_RasterImage == null) return;

            if (_gripName == "RightTop")
            {
                // 按缩放逻辑
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);

                var movePoint = mp.ToSKPoint();
                var point = this.vportRt.ConvertWcsToScr(_RasterImage.FirstPoint).ToSKPoint();
                canvas.DrawLine(point, movePoint, Constants.auxOrangeDashPen);

                var newscale = Vector2.Distance(_RasterImage.FirstPoint, wcs_mp) * this.vportRt.Viewport.Scale;
                var widthTmp = newscale;
                var heightTmp = newscale * _RasterImage.Height / _RasterImage.Width;

                canvas.DrawRect(point.X, point.Y, (float)widthTmp, -(float)heightTmp, Constants.auxElementPen);
            }
        }
    }
}
